package com.jdk21.core.config;

import com.alibaba.fastjson2.JSON;
import com.jdk21.api.common.Response;
import com.jdk21.api.enums.ErrorCodeEnum;
import com.jdk21.api.exceptions.CheckAdminLoginException;
import com.jdk21.api.exceptions.CheckUserLoginException;
import com.jdk21.core.manager.UserManager;
import com.jdk21.core.utils.IdUtil;
import jakarta.servlet.*;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

@Slf4j
public class LoginFilter implements Filter {

    private static final Set<String> NOT_VERIFY_URIS = new HashSet<>();
    private static final Set<String> NOT_VERIFY_PATH = new HashSet<>();

    private UserManager userManager;

    static {
        NOT_VERIFY_URIS.add("/login.html");
        NOT_VERIFY_URIS.add("/api/wechat");
        NOT_VERIFY_URIS.add("/swagger-ui.html");
        NOT_VERIFY_URIS.add("/file/upload");
    }

    public LoginFilter(UserManager userManager) {
        this.userManager = userManager;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        long start = System.currentTimeMillis();

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String method = request.getMethod();
        String url = request.getServletPath();

        if (!StringUtils.contains(url, "/file/download")) {
            response.setContentType("application/json;charset=utf-8");
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Methods", "GET, POST, HEAD,PUT,DELETE,OPTIONS");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
            response.setHeader("Cache-Control", "no-cache");
        }
        log.info("{}: {}", method, url);

        String requestURI = request.getRequestURI();
        try {
            String traceId = request.getHeader("TRACE_ID");
            if (StringUtils.isBlank(traceId)) {
                traceId = IdUtil.generateUUID();
            }

            MDC.put("TRACE_ID", traceId);

            if (notVerify(requestURI)) {
                if (!StringUtils.contains(url, "static")) {
                    log.info("no need login, requestURI:{}", requestURI);
                }
                doService(filterChain, request, response);
                return;
            }

            String authorizationToken = request.getHeader("Authorization");
            // 需要验证登录信息
            Cookie[] cookies = request.getCookies();
            if (cookies == null) {
//                log.warn("user login failed, requestURI:{}", requestURI);
//                response.getWriter().print(JSON.toJSONString(Response.failResult(ErrorCodeEnum.LOGIN_ERROR)));
//                response.getWriter().flush();
//                return;
            }
            String token = "";
            if (cookies != null) {
                for (Cookie cookie : cookies) {
                    if (StringUtils.equals(cookie.getName(), "token")) {
                        token = cookie.getValue();
                    }
                }
            }
            /*
            String username = userManager.getCookieMap().get(token);
            log.info("username:{} requestURI:{}", username, requestURI);
            if (StringUtils.isBlank(username)) {
                log.warn("user login failed, requestURI:{}", requestURI);
//                response.getWriter().print(JSON.toJSONString(Response.failResult(ErrorCodeEnum.LOGIN_ERROR)));
//                response.getWriter().flush();
                response.sendRedirect(request.getContextPath() + "/login.html");
                return;
            }
            */

//            UserDO userDO = userManager.getUserWithCache(token);
//            if (userDO == null) {
//                log.warn("user login failed, requestURI:{}", requestURI);
//                response.getWriter().print(JSON.toJSONString(Response.failResult(ErrorCodeEnum.LOGIN_ERROR)));
//                response.getWriter().flush();
//                return;
//            }
            // 登录信息验证通过
            doService(filterChain, request, response);
        } catch (Exception e) {
            log.error("http request Exception, url={}", url, e);
            response.getWriter().print(JSON.toJSONString(Response.failResult(ErrorCodeEnum.SYSTEM_ERROR)));
            response.getWriter().flush();
        } finally {
            if (!StringUtils.contains(url, "static")) {
                log.info("{}:{} execute cost={}", method, url, (System.currentTimeMillis() - start));
            }
            MDC.remove("TRACE_ID");
        }
    }

    public boolean notVerify(String uri) {
        if (StringUtils.contains(uri, "/static/")) {
            return true;
        }
        if (NOT_VERIFY_URIS.contains(uri)) {
            return true;
        }
        for (String s : NOT_VERIFY_PATH) {
            if (StringUtils.contains(uri, s)) {
                return true;
            }
        }
        return false;
    }

    private void doService(FilterChain filterChain, HttpServletRequest request, HttpServletResponse response) throws Exception {
        String url = request.getServletPath();
        try {
            filterChain.doFilter(request, response);
        } catch (Exception e) {
            if (e.getCause() instanceof CheckUserLoginException) {
                log.error("http request CheckUserLoginException, url={}", url, e);
                response.getWriter().print(JSON.toJSONString(Response.failResult(ErrorCodeEnum.USER_LOGIN_ERROR, ErrorCodeEnum.USER_LOGIN_ERROR.getDesc())));
                response.getWriter().flush();
                return;
            }
            if (e.getCause() instanceof CheckAdminLoginException) {
                log.error("http request CheckAdminLoginException, url={}", url, e);
                response.getWriter().print(JSON.toJSONString(Response.failResult(ErrorCodeEnum.ADMIN_LOGIN_ERROR, ErrorCodeEnum.ADMIN_LOGIN_ERROR.getDesc())));
                response.getWriter().flush();
                return;
            }
            if (e.getCause() instanceof IllegalArgumentException) {
                log.error("http request IllegalArgumentException, url={}", url, e);
                response.getWriter().print(JSON.toJSONString(Response.failResult(ErrorCodeEnum.PARAM_ERROR, e.getCause().getMessage())));
                response.getWriter().flush();
                return;
            }
            log.error("http request Exception, url={}", url, e);
            response.getWriter().print(JSON.toJSONString(Response.failResult(ErrorCodeEnum.SYSTEM_ERROR)));
            response.getWriter().flush();
        }
    }


    @Override
    public void destroy() {

    }
}
